package com.tencreat.service.mall.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.lock.annotation.Lock4j;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tencreat.common.core.domain.dto.AfterSaleDTO;
import com.tencreat.common.core.domain.entity.SysDictData;
import com.tencreat.common.core.domain.model.ReqIdParam;
import com.tencreat.common.core.domain.model.ReqIdsParam;
import com.tencreat.common.enums.*;
import com.tencreat.common.enums.mall.AllEnum;
import com.tencreat.common.exception.CustomException;
import com.tencreat.common.utils.DictUtils;
import com.tencreat.common.utils.RabbitSendUtils;
import com.tencreat.common.utils.spring.SpringUtils;
import com.tencreat.domain.account.MallUser;
import com.tencreat.domain.mall.*;
import com.tencreat.domain.mall.dto.AftersaleAuditDTO;
import com.tencreat.domain.mall.dto.CancelAftersaleDTO;
import com.tencreat.domain.mall.dto.MallAdminAfterSaleDTO;
import com.tencreat.domain.mall.vo.MallAdminAftersaleVO;
import com.tencreat.domain.mall.vo.MallAfterSaleCountVO;
import com.tencreat.domain.mall.vo.MallRefundCountVO;
import com.tencreat.mapper.mall.MallAftersaleMapper;
import com.tencreat.service.account.IMallUserService;
import com.tencreat.service.mall.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;

/**
 * 售后Service业务层处理
 *
 * @author tencreat
 * @date 2021-08-13
 */
@Service
@Transactional(rollbackFor = Exception.class)
@RequiredArgsConstructor
public class MallAftersaleServiceImpl extends ServiceImpl<MallAftersaleMapper, MallAftersale> implements IMallAftersaleService {

    private final IMallOrderGoodsService mallOrderGoodsService;
    private final IMallUserService mallUserService;
    private final IMallMessageInformService mallMessageInformService;
    private final IMallGoodsService goodsService;
    private final IMallDeliverAddressService mallDeliverAddressService;
    private final RabbitSendUtils rabbitUtils;
    private final IBalanceChangeService balanceChangeService;

    /**
     * 查询售后
     *
     * @param id 售后ID
     * @return 售后
     */
    @Override
    public MallAftersale selectMallAftersaleById(ReqIdParam id) {
        return baseMapper.selectById(id.getId());
    }

    /**
     * 查询售后列表
     *
     * @param mallAftersale 售后
     * @return 售后
     */
    @Override
    public List<MallAftersale> selectMallAftersaleList(MallAftersale mallAftersale) {
        return baseMapper.selectList(Wrappers.query(mallAftersale));
    }

    /**
     * 新增售后
     *
     * @param mallAftersale 售后
     * @return 结果
     */
    @Override
    public int insertMallAftersale(MallAftersale mallAftersale) {
        MallAftersale aftersale = lambdaQuery().eq(MallAftersale::getOrderSn, mallAftersale.getOrderSn()).one();
        if (aftersale != null) {
            throw new CustomException("已申请过售后！");
        }
        //根据订单号找到相关订单
        MallOrderGoods mallOrderGoods = mallOrderGoodsService.lambdaQuery().eq(MallOrderGoods::getId, mallAftersale.getOrderGoodsId()).one();
        //找到相关商品
        MallGoods mallGoods = goodsService.lambdaQuery().eq(MallGoods::getId, mallOrderGoods.getGoodsId()).one();
        if (mallGoods != null) {
            mallAftersale.setGoodsUserId(mallGoods.getUserId());
        }
        mallAftersale.setCreateTime(LocalDateTime.now());
        mallAftersale.setEndTime(LocalDateTimeUtil.offset(LocalDateTime.now(), 3, ChronoUnit.DAYS));
        mallAftersale.setAmount(mallOrderGoods.getPayPrice());
        int count = baseMapper.insert(mallAftersale);

        //将订单改为售后完成
        mallOrderGoodsService.lambdaUpdate().eq(MallOrderGoods::getId, mallOrderGoods.getId())
                .set(MallOrderGoods::getAftersaleStatus, AfterSaleStatus.DEL_PAY.getValue())
                .set(MallOrderGoods::getOrderStatus, OrderStatus.AFTERSALE_OK)
                .set(MallOrderGoods::getUpdateTime, LocalDateTime.now())
                .update();


        // 减少待结算货款
        //店铺
        BalanceChange balanceChange = new BalanceChange();
        if (mallOrderGoods.getOrderType().equals(OrderType.STORE)) {
            balanceChange = balanceChangeService.lambdaQuery()
                    .eq(BalanceChange::getSource, mallOrderGoods.getOrderGoodsSn())
                    .eq(BalanceChange::getBusinessType, BalanceBusinessType.STORE_SALE)
                    .eq(BalanceChange::getBalanceType, BalanceTypeEnum.STORE_FINANCE_WAIT)
                    .one();
            if (balanceChange != null) {
                rabbitUtils.sendBalanceMessage(balanceChange.getUuid(), balanceChange.getChangAmount().negate(), AllEnum.BalanceChangeTypeEnums.EXPENDITURE.getType(), BalanceBusinessType.GOODS_REFUND_V, "取消订单", balanceChange.getSource(), BalanceTypeEnum.STORE_FINANCE_WAIT);
            }

        }

        if (mallOrderGoods.getOrderType().equals(OrderType.SHOP)) {
            balanceChange = balanceChangeService.lambdaQuery()
                    .eq(BalanceChange::getSource, mallOrderGoods.getOrderGoodsSn())
                    .eq(BalanceChange::getBusinessType, BalanceBusinessType.ORDER_ADD)
                    .eq(BalanceChange::getBalanceType, BalanceTypeEnum.FINANCE_WAIT)
                    .one();
            if (balanceChange != null) {
                rabbitUtils.sendBalanceMessage(balanceChange.getUuid(), balanceChange.getChangAmount().negate(), AllEnum.BalanceChangeTypeEnums.EXPENDITURE.getType(), BalanceBusinessType.GOODS_REFUND_V, "取消订单", balanceChange.getSource(), BalanceTypeEnum.FINANCE_WAIT);
            }

        }

        // 减少待结算收益
        List<BalanceChange> list = balanceChangeService.lambdaQuery().eq(BalanceChange::getSource, mallOrderGoods.getOrderGoodsSn())
                .in(BalanceChange::getBusinessType, BalanceBusinessType.DIRECT_REFERRER, BalanceBusinessType.INDIRECT_REFERRER)
                .list();
        for (BalanceChange change : list) {
            rabbitUtils.sendBalanceMessage(change.getUuid(), change.getChangAmount().negate(), AllEnum.BalanceChangeTypeEnums.EXPENDITURE.getType(), BalanceBusinessType.GOODS_REFUND_V, "取消订单", change.getSource(), change.getBalanceType());
        }
        // 余额变动队列
        rabbitUtils.sendBalanceMessage(mallOrderGoods.getUuid(), mallOrderGoods.getPayPrice(), "1", BalanceBusinessType.GOODS_REFUND_V, "退款", mallOrderGoods.getOrderGoodsSn(), BalanceTypeEnum.CONSUMER_ROLL);
        mallMessageInformService.addOrderMessage("您的商品退款已完成", mallOrderGoods.getId(), mallOrderGoods.getUuid());

//        mallOrderGoodsService.updateById(mallOrderGoods);

        return baseMapper.updateById(mallAftersale);

    }

    /**
     * 审核通过 /退款
     *
     * @param mallAftersale 售后
     * @return 结果
     */
    @Override
    public int updateMallAftersale(AftersaleAuditDTO mallAftersale) {
        MallAftersale aftersale = lambdaQuery().eq(MallAftersale::getOrderGoodsId, mallAftersale.getOrderGoodsId()).one();
        aftersale.setUpdateTime(LocalDateTime.now());
        aftersale.setStatus(AfterSaleStatus.DEL_PAY.getValue());
        MallOrderGoods orderGoods = mallOrderGoodsService.lambdaQuery().eq(MallOrderGoods::getId, mallAftersale.getOrderGoodsId()).one();
        orderGoods.setAftersaleStatus(AfterSaleStatus.DEL_PAY.getValue());

        //将订单改为售后完成
        orderGoods.setOrderStatus(OrderStatus.OK);
        // 减少待结算货款
        //商城
        if (orderGoods.getOrderType().equals(OrderType.SHOP)) {
            BalanceChange balanceChange = balanceChangeService.lambdaQuery()
                    .eq(BalanceChange::getSource, orderGoods.getOrderGoodsSn())
                    .eq(BalanceChange::getBusinessType, BalanceBusinessType.ORDER_ADD)
                    .eq(BalanceChange::getBalanceType, BalanceTypeEnum.FINANCE_WAIT)
                    .one();
            if (balanceChange != null) {
                rabbitUtils.sendBalanceMessage(balanceChange.getUuid(), balanceChange.getChangAmount().negate(), AllEnum.BalanceChangeTypeEnums.EXPENDITURE.getType(), BalanceBusinessType.GOODS_REFUND_V, "取消订单", balanceChange.getSource(), BalanceTypeEnum.FINANCE_WAIT);
            }
            // 减少待结算收益
            List<BalanceChange> list = balanceChangeService.lambdaQuery().eq(BalanceChange::getSource, orderGoods.getOrderGoodsSn())
                    .in(BalanceChange::getBusinessType, BalanceBusinessType.DIRECT_REFERRER, BalanceBusinessType.INDIRECT_REFERRER)
                    .list();
            for (BalanceChange change : list) {
                rabbitUtils.sendBalanceMessage(change.getUuid(), change.getChangAmount().negate(), AllEnum.BalanceChangeTypeEnums.EXPENDITURE.getType(), aftersale.getType() != 2 ? BalanceBusinessType.GOODS_REFUND_V : BalanceBusinessType.GOODS_REFUND, "售后", change.getSource(), change.getBalanceType());
            }
        }
        //店铺
        if (orderGoods.getOrderType().equals(OrderType.STORE)) {
            BalanceChange balanceChange = balanceChangeService.lambdaQuery()
                    .eq(BalanceChange::getSource, orderGoods.getOrderGoodsSn())
                    .eq(BalanceChange::getBusinessType, BalanceBusinessType.STORE_SALE)
                    .eq(BalanceChange::getBalanceType, BalanceTypeEnum.STORE_FINANCE_WAIT)
                    .one();
            if (balanceChange != null) {
                rabbitUtils.sendBalanceMessage(balanceChange.getUuid(), balanceChange.getChangAmount().negate(), AllEnum.BalanceChangeTypeEnums.EXPENDITURE.getType(), BalanceBusinessType.GOODS_REFUND_V, "取消订单", balanceChange.getSource(), BalanceTypeEnum.STORE_FINANCE_WAIT);
            }
            // 减少待结算收益
            List<BalanceChange> list = balanceChangeService.lambdaQuery().eq(BalanceChange::getSource, orderGoods.getOrderGoodsSn())
                    .in(BalanceChange::getBusinessType, BalanceBusinessType.DIRECT_REFERRER, BalanceBusinessType.INDIRECT_REFERRER)
                    .list();
            for (BalanceChange change : list) {
                rabbitUtils.sendBalanceMessage(change.getUuid(), change.getChangAmount().negate(), AllEnum.BalanceChangeTypeEnums.EXPENDITURE.getType(), aftersale.getType() != 2 ? BalanceBusinessType.GOODS_REFUND_V : BalanceBusinessType.GOODS_REFUND, "售后", change.getSource(), change.getBalanceType());
            }
        }

        // 余额变动队列
        rabbitUtils.sendBalanceMessage(orderGoods.getUuid(), aftersale.getAmount(), "1", aftersale.getType() != 2 ? BalanceBusinessType.GOODS_REFUND_V : BalanceBusinessType.GOODS_REFUND, "", orderGoods.getOrderGoodsSn(), BalanceTypeEnum.BALANCE);
        mallMessageInformService.addOrderMessage("您的商品售后已完成", orderGoods.getId(), orderGoods.getUuid());

        mallOrderGoodsService.updateById(orderGoods);

        return baseMapper.updateById(aftersale);
    }


    /**
     * 取消售后
     *
     * @param mallAftersale
     * @return 结果
     */
    @Override
    public int cancelAfterSale(CancelAftersaleDTO mallAftersale) {
        MallOrderGoods order = mallOrderGoodsService.getById(mallAftersale.getOrderGoodsId());
        order.setAftersaleStatus(AfterSaleStatus.CANCELLED.getValue());
        order.setUpdateTime(LocalDateTime.now());
        mallOrderGoodsService.updateById(order);
        MallAftersale aftersale = lambdaQuery().eq(MallAftersale::getOrderGoodsId, mallAftersale.getOrderGoodsId()).one();
        aftersale.setStatus(AfterSaleStatus.CANCELLED.getValue());
        aftersale.setUpdateTime(LocalDateTime.now());
        return baseMapper.updateById(aftersale);
    }

    /**
     * 退款退货通过
     *
     * @param mallAftersale
     * @return
     */
    @Override
    public int auditMallAftersale(AftersaleAuditDTO mallAftersale) {
        MallAftersale aftersale = lambdaQuery().eq(MallAftersale::getOrderGoodsId, mallAftersale.getOrderGoodsId()).one();
        MallOrderGoods orderGoods = mallOrderGoodsService.lambdaQuery().eq(MallOrderGoods::getId, mallAftersale.getOrderGoodsId()).one();
        MallGoods mallGoods = goodsService.lambdaQuery().eq(MallGoods::getId, orderGoods.getGoodsId()).one();
        // 获取用户的退货地址
        MallDeliverAddress mallDeliverAddress = mallDeliverAddressService.lambdaQuery().eq(MallDeliverAddress::getUserId, mallGoods.getUserId()).eq(MallDeliverAddress::getDeliverType, 1).select(MallDeliverAddress::getId).one();
        if (mallDeliverAddress == null) {
            throw new CustomException("请先设置退货地址!");
        }

        orderGoods.setAftersaleStatus(AfterSaleStatus.BUYER_DEAL.getValue());
        orderGoods.setAddressId(mallDeliverAddress.getId());
        mallOrderGoodsService.updateById(orderGoods);

        aftersale.setUpdateTime(LocalDateTime.now());
        aftersale.setAddressId(mallDeliverAddress.getId());
        aftersale.setStatus(AfterSaleStatus.BUYER_DEAL.getValue());
        aftersale.setEndTime(LocalDateTimeUtil.offset(LocalDateTime.now(), 3, ChronoUnit.DAYS));

        int update = baseMapper.updateById(aftersale);
        if (update > 0) {
            // 买家三天未处理自动取消售后
            AfterSaleDTO dto = new AfterSaleDTO();
            dto.setOrderGoodsId(mallAftersale.getOrderGoodsId());
            dto.setOrderId(aftersale.getOrderId());
            dto.setId(aftersale.getId());
            sendDelayMessageAfterSaleBack(dto, 3);
        }
        return update;
    }


    /**
     * 审核拒绝
     *
     * @param mallAftersale 售后
     * @return 结果
     */
    @Override
    public int refuseMallAftersale(AftersaleAuditDTO mallAftersale) {
        MallAftersale aftersale = lambdaQuery().eq(MallAftersale::getOrderGoodsId, mallAftersale.getOrderGoodsId()).one();
        aftersale.setUpdateTime(LocalDateTime.now());
        aftersale.setStatus(AfterSaleStatus.DAI_CENTXT.getValue());

        MallOrderGoods orderGoods = mallOrderGoodsService.lambdaQuery().eq(MallOrderGoods::getId, mallAftersale.getOrderGoodsId()).one();
        orderGoods.setAftersaleStatus(AfterSaleStatus.DAI_CENTXT.getValue());
        mallOrderGoodsService.updateById(orderGoods);

        return baseMapper.updateById(aftersale);
    }

    /**
     * 买家未填写退货物流 自动取消
     *
     * @param dto
     * @param days 天
     */
    private void sendDelayMessageAfterSaleBack(AfterSaleDTO dto, long days) {
        long delayTimes = days * 24 * 60 * 60 * 1000;
        if (SpringUtils.isNotProd()) {
            delayTimes = days * 1000 * 60;
        }
        // 随机生成1-100数，用来同一时间处理队列
        int num = (int) (Math.random() * 50);
        delayTimes = delayTimes + num;
        //发送延迟消息
        rabbitUtils.sendMessageAfterSaleBack(dto, delayTimes);
    }

    /**
     * 平台未处理自动确认
     *
     * @param dto
     * @param days 天
     */
    @Override
    public void sendDelayMessageAfterSale(AfterSaleDTO dto, long days) {
        long delayTimes = days * 24 * 60 * 60 * 1000;
        if (SpringUtils.isNotProd()) {
            delayTimes = days * 1000 * 60;
        }
        // 随机生成1-100数，用来同一时间处理队列
        int num = (int) (Math.random() * 50);
        delayTimes = delayTimes + num;
        //发送延迟消息
        rabbitUtils.sendMessageAfterSale(dto, delayTimes);
    }

    @Override
    public IPage<MallAdminAftersaleVO> pages(IPage<?> page, MallAdminAfterSaleDTO dto) {
        return baseMapper.pages(page, dto);
    }

    @Override
    public MallAfterSaleCountVO afterSaleCount() {
        MallAfterSaleCountVO vo = new MallAfterSaleCountVO();

        // 全部
        int count = lambdaQuery().count();
        vo.setAllCount(count);

        // 待处理
        int count1 = lambdaQuery().eq(MallAftersale::getStatus, 1).count();
        vo.setWaitMerchantsCount(count1);

        // 退货中
        int count3 = lambdaQuery().eq(MallAftersale::getStatus, 8).count();
        vo.setGoodsReturnCount(count3);

        // 已拒绝
        int count4 = lambdaQuery().eq(MallAftersale::getStatus, 4).count();
        vo.setRefuseCount(count4);

        // 已完成
        int count5 = lambdaQuery().in(MallAftersale::getStatus, 3, 5).count();
        vo.setOverCount(count5);
        return vo;
    }

    @Override
    public MallRefundCountVO refundCount() {
        LocalDateTime now = LocalDateTime.now();
        MallRefundCountVO vo = new MallRefundCountVO();
        // 售后总金额
        BigDecimal refundCount = baseMapper.refundCount(null, null);
        vo.setRefundCount(refundCount);
        // 今日售后总金额
        BigDecimal todayRefundCount = baseMapper.refundCount(null, now);
        vo.setTodayRefundCount(todayRefundCount);
        // 待审核金额
        BigDecimal waitAuditCount = baseMapper.refundCount(1, null);
        vo.setWaitAuditCount(waitAuditCount);
        // 今日待审核金额
        BigDecimal todayWaitAuditCount = baseMapper.refundCount(1, now);
        vo.setTodayWaitAuditCount(todayWaitAuditCount);
        // 退货中金额
        BigDecimal arbitrationCount = baseMapper.refundCount(2, null);
        vo.setArbitrationCount(arbitrationCount);
        // 今日退货中金额
        BigDecimal todayArbitrationCount = baseMapper.refundCount(2, now);
        vo.setTodayArbitrationCount(todayArbitrationCount);
        // 已完成金额
        BigDecimal overCount = baseMapper.refundCount(3, null);
        vo.setOverCount(overCount);
        // 今日已完成金额
        BigDecimal todayOverCount = baseMapper.refundCount(3, now);
        vo.setTodayOverCount(todayOverCount);
        // 已拒绝金额
        BigDecimal refuseCount = baseMapper.refundCount(4, null);
        vo.setRefuseCount(refuseCount);
        // 今日已拒绝金额
        BigDecimal todayRefuseCount = baseMapper.refundCount(4, now);
        vo.setTodayRefuseCount(todayRefuseCount);

        return vo;
    }

    /**
     * 批量删除售后
     *
     * @param ids 需要删除的售后ID
     * @return 结果
     */
    @Override
    public int deleteMallAftersaleByIds(ReqIdsParam ids) {
        return baseMapper.deleteBatchIds(ids.getId());
    }

    /**
     * 删除售后信息
     *
     * @param id 售后ID
     * @return 结果
     */
    @Override
    public int deleteMallAftersaleById(ReqIdParam id) {
        return baseMapper.deleteById(id.getId());
    }
}
